# frozen_string_literal: true

class RuleEntity
  class GeneralRule < RuleEntity
    # self.abstract_class = true
    self.inheritance_column = :_type_disabled

    has_many :rule_outputs, -> { ordinal_asc }, dependent: :destroy

    def fire_without_validate(params)
      return [] unless only_fire?(params)

      build_fire_outputs(params).map { |outputs| schema.format_outputs(outputs) }
    end

    def only_fire?(_params)
      false
    end

    def build_archive_params
      raise 'Unsupported.'
    end

    def deep_clone_to_draft
      entity = super
      entity.rule_outputs = rule_outputs.map(&:deep_clone_to_draft)
      entity
    end

    def update_draft(params)
      super
      update_outputs(params[:rule_outputs]) if params[:rule_outputs].present?
    end

    def force_validate
      super

      validate_outputs
    end

    def build_fire_outputs(params)
      [rule_outputs.map { |output| [output.name, output.fire(params)] }.to_h]
    end

    private

    def update_outputs(outputs_params)
      ordinal = 0
      rule_outputs.zip(outputs_params) do |output, params|
        if params.present?
          output.update! build_update_output_params(ordinal, params)
        else
          output.destroy!
        end
        ordinal += 1
      end

      outputs_params[ordinal..]&.each_with_index do |params, index|
        output = rule_outputs.create! build_update_output_params(ordinal + index, params)
        output.create_formula! params.require(:formula) if output.is_a?(RuleOutput::Dsl)
      end
    end

    def build_update_output_params(ordinal, params)
      { ordinal: ordinal, name: params[:name], type: params[:type], value: params[:value] }
    end

    def validate_outputs
      temp = rule_outputs.index_by(&:name)

      schema.output_variables.each_with_index do |variable, ordinal|
        raise 'schema.schema_variables 顺序号错误' unless variable.ordinal.eql?(ordinal)

        output = temp.delete variable.name
        raise "outputs 缺少参数，#{variable.name}" if variable.required? && !output

        output.validate(variable.variable_type)
      end

      raise "schema 缺少参数，#{temp}" if temp.present?
    end
  end
end
